package solutions.ferpa.ztest.intf;

import br.com.telescope.adsrt.dom.DomFlag;
import br.com.telescope.adsrt.dom.DomId;
import br.com.telescope.adsrt.dom.DomOpcao;
import br.com.telescope.adsrt.dom.DomSourceCode;
import br.com.telescope.adsrt.dom.DomText;
import br.com.telescope.adsrt.dom.DomTextLong;
import br.com.telescope.adsrt.dom.DomUpper;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.adsrt.lib.AdsException;
import br.com.telescope.adsrt.lib.Form;
import br.com.telescope.sql.ModelQuery;
import br.com.telescope.t2.ServiceModel;
import br.com.telescope.t2.exception.ApplicationRuntimeException;
import br.com.telescope.t2.exception.UnexpectedException;
import br.com.telescope.t2.feature.CustomActionFeature;
import br.com.telescope.t2.feature.DeleteFeature;
import br.com.telescope.t2.feature.InsertFeature;
import br.com.telescope.t2.feature.ListFeature;
import br.com.telescope.t2.feature.LookupFeature;
import br.com.telescope.t2.feature.QueryFeature;
import br.com.telescope.t2.feature.RecordActionFeature;
import br.com.telescope.t2.feature.SearchFeature;
import br.com.telescope.t2.feature.UpdateFeature;
import br.com.telescope.t2.feature.ViewFeature;
import br.com.telescope.util.ObjectUtil;
import javax.script.ScriptEngine;
import solutions.ferpa.ztest.ent.*;

/**
 * Operações customizadas.
 * <p>
 * Interface que permite manter operações customizadas do sistema, tais 
 * como scripts ou chamadas a outras rotinas externas.
 * <P>
 * 
 * <P>
 * As rotinas programadas aqui podem ser agendadas para serem executadas 
 * automaticamente através do [t:#422754;title].
 * <P>
 * 
 * <P>
 * Telescope origin: RTSYSINF.CAD_OPERACOES_CUSTOM
 * <P>
 * Base entity: RTSYSINF.OPERACOES_SISTEMAS
 * <P>
 * @author TELESCOPE - Build task T2 Web Interface Generator
 * <P>
 * @version 0.1
 */
public class CadOperacoesCustom extends ServiceModel {
    
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    public static final String GLOBAL_NAME = "RTSYSINF.CAD_OPERACOES_CUSTOM";
    
    @Override
    public String globalName() {
        return GLOBAL_NAME;
    }
    
    {
        setTitle("Operações customizadas");
    }
    
    protected EntOperacoesSistemas base;
    protected EntTiposImplementacoes tipo;
    protected EntOperacoesSistemas rec; // NEED_TJW1_COMPATIBILITY
    
    // Record items
    private DomUpper aOperacao;
    private DomText aTitulo;
    private DomSourceCode aImplementacao;
    private DomOpcao aPoliticaAcesso;
    private DomTextLong aDescricao;
    private DomOpcao aTipo;
    private DomOpcao aTiposImplementacoes;
    private DomFlag aScript;
    private DomId aId;
    
    // Query items
    private DomSourceCode qImplementacao;
    private DomTextLong qDescricao;
    private DomText qTitulo;
    private DomUpper qOperacao;
    private DomOpcao qPoliticaAcesso;
    private DomOpcao qTiposImplementacoes;
    
    @Override
    public void copyDefaultValues() {
        copyDefaultValue(base.getTipo(), aTipo);
    }
    
    @Override
    public String getBaseSql() {
        return "select BASE.*"
                + " , TIPO.TIPO_IMPLEMENTACAO as TIPOS_IMPLEMENTACOES"
                + " , TIPO.SCRIPT as SCRIPT"
                + " , TIPO.ID as Z_TIPO_ID"
                + " from OPERACOES_SISTEMAS BASE"
                + " left join TIPOS_IMPLEMENTACOES TIPO on TIPO.ID = BASE.TIPO_IMPLEMENTACAO_ID";
    }
    
    @Override
    public String getBaseSqlWhereClause() {
        
        return " where base.tipo='I'";
    }
    
    @Override
    public void initAttributes() {
        
        aOperacao = new DomUpper();
        aOperacao.context(ctx).name("OPERACAO").label("Operação");
        
        aTitulo = new DomText();
        aTitulo.context(ctx).name("TITULO").label("Título");
        
        aImplementacao = new DomSourceCode();
        aImplementacao.context(ctx).name("IMPLEMENTACAO").label("Implementação");
        
        aPoliticaAcesso = new DomOpcao();
        aPoliticaAcesso.context(ctx).name("POLITICA_ACESSO").label("Política de acesso").group(true);
        aPoliticaAcesso.addOption("P", "Público");
        aPoliticaAcesso.addOption("R", "Restrito");
        aPoliticaAcesso.addOption("U", "Usuário");
        aPoliticaAcesso.setDefaultValue("R");
        
        aDescricao = new DomTextLong();
        aDescricao.context(ctx).name("DESCRICAO").label("Descrição");
        
        aTipo = new DomOpcao();
        aTipo.context(ctx).name("TIPO").label("Tipo").group(true);
        aTipo.addOption("I", "Implementação custom");
        aTipo.addOption("R", "Report");
        aTipo.addOption("S", "Service");
        aTipo.addOption("U", "User interface");
        aTipo.setDefaultValue("I");
        
        aTiposImplementacoes = new DomOpcao();
        aTiposImplementacoes.context(ctx).name("TIPOS_IMPLEMENTACOES").label("Tipo de implementacao").group(true);
        
        aTiposImplementacoes.setSqlOptions("SELECT TIPO_IMPLEMENTACAO, TIPO_IMPLEMENTACAO FROM TIPOS_IMPLEMENTACOES TIPO ORDER BY 1");
        
        aScript = new DomFlag();
        aScript.context(ctx).name("SCRIPT").label("Script");
        aScript.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT SCRIPT as valor"
                + " , SCRIPT as pesquisar"
                + " , SCRIPT as descricao"
                + " from TIPOS_IMPLEMENTACOES TIPO)", "q"));
        aScript.setAutocompleteLength(0);
        aScript.setDefaultValue("S");
        
        aId = new DomId();
        aId.context(ctx).name("ID").label("Id");
        
        
        qImplementacao = new DomSourceCode();
        qImplementacao.context(ctx).name("IMPLEMENTACAO").label("Implementação");
        
        qDescricao = new DomTextLong();
        qDescricao.context(ctx).name("DESCRICAO").label("Descrição");
        
        qTitulo = new DomText();
        qTitulo.context(ctx).name("TITULO").label("Título");
        
        qOperacao = new DomUpper();
        qOperacao.context(ctx).name("OPERACAO").label("Operação");
        
        qPoliticaAcesso = new DomOpcao();
        qPoliticaAcesso.context(ctx).name("POLITICA_ACESSO").label("Política de acesso");
        qPoliticaAcesso.addOption("P", "Público");
        qPoliticaAcesso.addOption("R", "Restrito");
        qPoliticaAcesso.addOption("U", "Usuário");
        
        qTiposImplementacoes = new DomOpcao();
        qTiposImplementacoes.context(ctx).name("TIPOS_IMPLEMENTACOES").label("Tipo de implementacao");
        
        qTiposImplementacoes.setSqlOptions("SELECT TIPO_IMPLEMENTACAO, TIPO_IMPLEMENTACAO FROM TIPOS_IMPLEMENTACOES TIPO ORDER BY 1");
    }
    
    @Override
    public String getQueryPkColumn() {
        return "BASE.ID";
    }
    
    @Override
    public void setId(String value) {
        this.aId.setValue(value);
    }
    
    @Override
    public EntOperacoesSistemas getRecord() {
        if (base == null) {
            base = new EntOperacoesSistemas(ctx);
            rec = base;
        }
        return this.base;
    }
    
    @Override
    public String getContextName() {
        return aOperacao.toText();
    }
    
    @Override
    public String getDefaultOrderBy() {
        return "OPERACAO, TITULO, TIPOS_IMPLEMENTACOES, POLITICA_ACESSO";
    }
    
    @Override
    public void translateInsertFks(Form form) {
        ModelQuery query;
        
        // TIPO_IMPLEMENTACAO_ID
        try {
            if (form.hasFields("TIPOS_IMPLEMENTACOES")) {
                query = createQuery()
                        .select("TIPO.ID")
                        .from("TIPOS_IMPLEMENTACOES", "TIPO")
                        .filter("TIPO.TIPO_IMPLEMENTACAO", form.get("TIPOS_IMPLEMENTACOES"))
                        ;
                base.setTipoImplementacaoId(ObjectUtil.toLong(translateFk(query)));
            }
        } catch (AdsException ex) {
            throw new RuntimeException(ex);
        }
    }
    
    @Override
    public void translateUpdateFks(Form form) {
        ModelQuery query;
        
        // TIPO_IMPLEMENTACAO_ID
        try {
            if (form.hasFields("TIPOS_IMPLEMENTACOES")) {
                query = createQuery()
                        .select("TIPO.ID")
                        .from("TIPOS_IMPLEMENTACOES", "TIPO")
                        .filter("TIPO.TIPO_IMPLEMENTACAO", form.get("TIPOS_IMPLEMENTACOES"))
                        ;
                base.setTipoImplementacaoId(ObjectUtil.toLong(translateFk(query)));
            }
        } catch (AdsException ex) {
            throw new RuntimeException(ex);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="QUERY">
    public class FQuery extends QueryFeature {
        
        @Override
        public void initForm() {
            addField(qOperacao, "opt");
            addField(qTitulo, "opt");
            addField(qTiposImplementacoes, "opt");
            addField(qImplementacao, "opt");
            addField(qPoliticaAcesso, "opt");
        }
        
        {
            setFeatureName("QUERY");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="SEARCH">
    public class FSearch extends SearchFeature {
        
        @Override
        public void initForm() {
            addField(qOperacao, "search");
            addField(qTitulo, "search");
            addField(qImplementacao, "search");
            addField(qDescricao, "search");
        }
        
        {
            setFeatureName("SEARCH");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="LIST">
    public class FList extends ListFeature {
        
        @Override
        public void initForm() {
            addField(aOperacao, "view");
            addField(aTitulo, "view");
            addField(aTiposImplementacoes, "view");
            addField(aPoliticaAcesso, "view");
        }
        
        {
            setFeatureName("LIST");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="INSERT">
    public class FInsert extends InsertFeature {
        
        @Override
        public void initForm() {
            aOperacao.setOptional(false);
            addField(aOperacao, "rqd");
            aTitulo.setOptional(false);
            addField(aTitulo, "rqd");
            aTiposImplementacoes.setOptional(false);
            addField(aTiposImplementacoes, "rqd");
            aImplementacao.setOptional(false);
            addField(aImplementacao, "rqd");
            aPoliticaAcesso.setOptional(false);
            addField(aPoliticaAcesso, "rqd");
            addField(aDescricao, "opt");
        }
        
        {
            setFeatureName("INSERT");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="UPDATE">
    public class FUpdate extends UpdateFeature {
        
        @Override
        public void initForm() {
            aOperacao.setOptional(false);
            addField(aOperacao, "rqd");
            aTitulo.setOptional(false);
            addField(aTitulo, "rqd");
            aTiposImplementacoes.setOptional(false);
            addField(aTiposImplementacoes, "rqd");
            aImplementacao.setOptional(false);
            addField(aImplementacao, "rqd");
            aPoliticaAcesso.setOptional(false);
            addField(aPoliticaAcesso, "rqd");
            addField(aDescricao, "opt");
        }
        
        {
            setFeatureName("UPDATE");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="DELETE">
    public class FDelete extends DeleteFeature {
        
        @Override
        public void initForm() {
            addField(aOperacao, "view");
        }
        
        {
            setFeatureName("DELETE");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="VIEW">
    public class FView extends ViewFeature {
        
        @Override
        public void initForm() {
            addField(aOperacao, "view");
            addField(aTitulo, "view");
            addField(aTiposImplementacoes, "view");
            addField(aImplementacao, "view");
            addField(aPoliticaAcesso, "view");
            addField(aDescricao, "view");
        }
        
        {
            setFeatureName("VIEW");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="EXECUTAR">
    public class FExecutar extends RecordActionFeature {
        
        @Override
        public void initForm() {
        }
        
        @Override
        public void execute() {
            try {
                executar();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("EXECUTAR");
            setTitle("Executar");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="EXEC">
    public class FExec extends CustomActionFeature {
        
        @Override
        public void initForm() {
        }
        
        @Override
        public void execute() {
            try {
                exec();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("EXEC");
            setTitle("Executar (sem interface)");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="TIPOS_IMPLEMENTACOES_LOOKUP">
    public class FTiposImplementacoesLookup extends LookupFeature {
        
        @Override
        public void initForm() {
            aTiposImplementacoes.setEditable(true);
            addField(aTiposImplementacoes, "opt");
            aScript.setEditable(false);
            addField(aScript, "view");
        }
        
        @Override
        public ModelQuery getLookupQuery() {
            return createQuery()
                    .select("TIPO.TIPO_IMPLEMENTACAO as TIPOS_IMPLEMENTACOES")
                    .select("TIPO.SCRIPT as SCRIPT")
                    .from("TIPOS_IMPLEMENTACOES", "TIPO")
                    ;
        }
        
        {
            setFeatureName("TIPOS_IMPLEMENTACOES_LOOKUP");
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="initFeatures">
    
    @Override
    protected void initFeatures() {
        addFeature(new FQuery());
        addFeature(new FSearch());
        addFeature(new FList());
        addFeature(new FInsert());
        addFeature(new FUpdate());
        addFeature(new FDelete());
        addFeature(new FView());
        addFeature(new FExecutar());
        addFeature(new FExec());
        addFeature(new FTiposImplementacoesLookup());
        super.initFeatures();
    }
    
    @Override
    public String getDefaultFeature() {
        return "QUERY";
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Getters and Setters">
    
    public String getOperacao() {
        return aOperacao.getValue();
    }
    
    public void setOperacao(String value) {
        this.aOperacao.setValue(value);
    }
    
    public String getTitulo() {
        return aTitulo.getValue();
    }
    
    public void setTitulo(String value) {
        this.aTitulo.setValue(value);
    }
    
    public String getImplementacao() {
        return aImplementacao.getValue();
    }
    
    public void setImplementacao(String value) {
        this.aImplementacao.setValue(value);
    }
    
    public String getPoliticaAcesso() {
        return aPoliticaAcesso.getValue();
    }
    
    public void setPoliticaAcesso(String value) {
        this.aPoliticaAcesso.setValue(value);
    }
    
    public String getDescricao() {
        return aDescricao.getValue();
    }
    
    public void setDescricao(String value) {
        this.aDescricao.setValue(value);
    }
    
    public String getTipo() {
        return aTipo.getValue();
    }
    
    public void setTipo(String value) {
        this.aTipo.setValue(value);
    }
    
    public String getTiposImplementacoes() {
        return aTiposImplementacoes.getValue();
    }
    
    public void setTiposImplementacoes(String value) {
        this.aTiposImplementacoes.setValue(value);
    }
    
    public String getScript() {
        return aScript.getValue();
    }
    
    public void setScript(String value) {
        this.aScript.setValue(value);
    }
    
    @Override
    public Long getId() {
        return aId.getValue();
    }
    
    public void setId(Long value) {
        this.aId.setValue(value);
    }
    public String getQueryOperacao() {
        return qOperacao.getQueryValue();
    }
    
    public void setQueryOperacao(String value) {
        this.qOperacao.setQueryValue(value);
    }
    public String getQueryTitulo() {
        return qTitulo.getQueryValue();
    }
    
    public void setQueryTitulo(String value) {
        this.qTitulo.setQueryValue(value);
    }
    public String getQueryTiposImplementacoes() {
        return qTiposImplementacoes.getQueryValue();
    }
    
    public void setQueryTiposImplementacoes(String value) {
        this.qTiposImplementacoes.setQueryValue(value);
    }
    public String getQueryImplementacao() {
        return qImplementacao.getQueryValue();
    }
    
    public void setQueryImplementacao(String value) {
        this.qImplementacao.setQueryValue(value);
    }
    public String getQueryPoliticaAcesso() {
        return qPoliticaAcesso.getQueryValue();
    }
    
    public void setQueryPoliticaAcesso(String value) {
        this.qPoliticaAcesso.setQueryValue(value);
    }
    // </editor-fold>
    
    /**
     * Executar.
     * <p>
     * Executa o script
     */
    public void executar() throws AdsException {
        // <user-code id="2505872" parentId="2505870" hashcode="58feea3c" length="510">
        // import javax.script.ScriptEngine;
        // import br.com.telescope.t2.exception.UnexpectedException;
        try {
            tipo = getRecord().findTipoImplementacao();
            String classname = tipo.valueOfMecanismoExecucao();
            Class clazz = Class.forName(classname);
            ScriptEngine engine = (ScriptEngine) clazz.newInstance();
            engine.put("ctx", ctx);
            engine.eval(getRecord().valueOfImplementacao());
        } catch (Exception ex) {
            throw new UnexpectedException("Não foi possivel executar o script!", ex);
        }
        // </user-code>
    }
    
    /**
     * Executar (sem interface).
     * <p>
     * Executa o script pura e simplesmente (sem apresentar esta interface).
     * <P>
     * Esta função é utilizada para ser executada a partir do menu do 
     * sistema.
     * <P>
     */
    public void exec() throws AdsException {
        // <user-code id="2555589" parentId="2555583" hashcode="48615f30" length="849">
        // import javax.script.ScriptEngine;
        // import br.com.telescope.t2.exception.UnexpectedException;
        try {
            Long id = Long.parseLong(ctx.getParameter("A_ID"));
            EntOperacoesSistemas oper = new EntOperacoesSistemas(ctx);
            oper.filterBy().equal(oper.getInterfaceId(), id);
            if (oper.next()) {
                setTitle(getRecord().valueOfTitulo());
                tipo = oper.findTipoImplementacao();
                String classname = tipo.valueOfMecanismoExecucao();
                Class clazz = Class.forName(classname);
                ScriptEngine engine = (ScriptEngine) clazz.newInstance();
                engine.put("ctx", ctx);
                engine.eval(oper.valueOfImplementacao());
            } else {
                throw new UnexpectedException("Script inválido!");
            }
        } catch (Exception ex) {
            throw new UnexpectedException("Não foi possivel executar o script!", ex);
        }
        // </user-code>
    }
    
    @Override
    public String getJsServiceFile() {
        return "ui/rtsysinf/cad_operacoes_custom.js";
    }
}
